package br.ufpa.cbcc2007.dikemon.map;

import java.io.InputStream;

import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.game.Sprite;

import br.ufpa.cbcc2007.dikemon.engine.Engine;
import br.ufpa.cbcc2007.dikemon.engine.Scene;
import br.ufpa.cbcc2007.dikemon.exception.MapNotFoundException;
import br.ufpa.cbcc2007.dikemon.util.TextBox;

//Classe que representa uma visão dinâmica do mapa ativo. Como esta classe é singleton, pode haver apenas
// um único mapa ATIVO por vez, por mais que haja outros que carregados
public class MapScene implements Scene {
	private Map actualMap = null;		//mapa atual
	private TextBox textBox;			//Caixa de texto, se houver
	private int keyStates;				//Estado atual dos botões, é atualizado uma vez por frame.

	static private MapScene mapScene;	//instancia única
	
	//Construtor
	public MapScene() {
		setMapScene(this);
	}

	//Método que faz a atualização lógica do jogo
	public void actualize(int keyStates){

		this.keyStates =keyStates;					//Atualiza o estado dos botões
		
		//Atualização dos Sprites atualizaveis
		int num = actualMap.actualizables.size();
		for(int i = 0; i < num; ++i){
			((Actualizeable)actualMap.actualizables.elementAt(i)).actualize();
		}
		
		//Checagem de colisão
		num =  actualMap.collideables.size();
		for(int i=0; i< num; ++i){
			Collideable obj1 = ((Collideable)actualMap.collideables.elementAt(i));
			//Checagem com outros Sprites
			for (int j = i+1; j < num; j++) {
				Collideable obj2 = (Collideable)actualMap.collideables.elementAt(j);
				if(((Sprite) obj1).collidesWith((Sprite)obj2, false)){
					obj1.collides(obj2);
					obj2.collides(obj1);
				}
			}
			//Checagem com os tiles do layer Middle.
			if(((Sprite) obj1).collidesWith(actualMap.middle, false))obj1.collidesTile();
		}
		
		//Se estiver seguindo um Sprite, será ajustado à tela automaticamente.
		if (actualMap.follow && actualMap.spriteFollowed != null) {
			actualMap.offsetX = actualMap.spriteFollowed.getX() - actualMap.size/2 + actualMap.spriteFollowed.getWidth()/2;
			actualMap.offsetY = actualMap.spriteFollowed.getY() - actualMap.size/2 + actualMap.spriteFollowed.getHeight()/2;
			actualMap.layerManager.setViewWindow(actualMap.offsetX, actualMap.offsetY, actualMap.size, actualMap.size);
		}
	}
	
	//Aqui é realizada a atualização da tela.
	public void paint(Graphics graphics, int x, int y) {
		//Atualização das camadas
		actualMap.layerManager.paint(graphics, x, y);
		//Atualização da caixa de texto, se houver
		if(textBox != null){
			textBox.paint(graphics);
		}
	}

	public void setActualMap(Map actualMap) {
		this.actualMap = actualMap;
	}
	
	public void setActualMap(String mapName) throws MapNotFoundException {
		InputStream resourceAsStream = Engine.getEngine().getClass().getResourceAsStream("/maps/"+mapName+".map");
		if(resourceAsStream == null) throw new MapNotFoundException(mapName);
		actualMap = new Loader(resourceAsStream).load(Engine.TILESIZE);
	}

	public Map getActualMap() {
		return actualMap;
	}

	public static void setMapScene(MapScene mapScene) {
		MapScene.mapScene = mapScene;
	}

	public static MapScene getMapScene() {
		return mapScene;
	}

	public int getKeyState() {
		return keyStates;
	}
	
	public TextBox getTextBox() {
		return textBox;
	}

	public void setTextBox(TextBox textBox) {
		this.textBox = textBox;
	}

}
